package com.mulong.mall.aop;

import java.util.*;

import jakarta.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson2.JSON;
import com.mulong.common.exception.ErrorEnums;
import com.mulong.common.exception.MulongException;
import com.mulong.common.util.MulongUtil;
import com.mulong.common.util.RequestContext;
import com.mulong.mall.domain.bo.AccessToken;
import com.mulong.mall.util.MallRequestContext;
import com.mulong.mall.web.api.OauthApi;

import lombok.extern.slf4j.Slf4j;

/**
 * ApiAspect
 * 
 * @author mulong
 * @data 2021-04-06 14:05:49
 */
@Slf4j
@Aspect
@Component
public class ApiAspect {

    @Pointcut("execution(* com.mulong.mall.web.api..*Api.*(..))")
    public void api() {
        // Do nothing
    }

    @Before(value = "api()")
    public void before(JoinPoint joinPoint) {
        String targetClassName = joinPoint.getTarget().getClass().getName();
        String functionName = joinPoint.getSignature().getName();
        if (OauthApi.class.getName().equals(targetClassName) && "token".equalsIgnoreCase(functionName)) {
            return;
        }
        HttpServletRequest request = RequestContext.getRequest();
        String token = request.getHeader("Authorization");
        log.info("token [{}]", token);
        if (StringUtils.isBlank(token)) {
            throw new MulongException(ErrorEnums.VALID_ACCESS_TOKEN_ERROR);
        }
        String data = null;
        try {
            data = MulongUtil.desDecrypt(token);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MulongException(ErrorEnums.VALID_ACCESS_TOKEN_ERROR);
        }
        if (StringUtils.isBlank(data)) {
            throw new MulongException(ErrorEnums.VALID_ACCESS_TOKEN_ERROR);
        }
        AccessToken accessToken = null;
        try {
            accessToken = JSON.parseObject(data, AccessToken.class);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MulongException(ErrorEnums.VALID_ACCESS_TOKEN_ERROR);
        }
        if (accessToken == null) {
            throw new MulongException(ErrorEnums.VALID_ACCESS_TOKEN_ERROR);
        }
        if (isAccessTokenExpired(accessToken)) {
            throw new MulongException(ErrorEnums.ACCESS_TOKEN_EXPIRED);
        }
        MallRequestContext.init(accessToken);
        log.info("Username [{}] Usertype [{}]", MallRequestContext.getUsername(), MallRequestContext.getUsertype().getCode());
    }

    private boolean isAccessTokenExpired(AccessToken accessToken) {
        Date now = new Date();
        if (accessToken.getExpiredTime() != null) {
            if (now.before(accessToken.getExpiredTime())) {
                return false;
            }
            return true;
        }
        return true;
    }

}
